#include <QDebug>
#include <QMutexLocker>

#include "dllqlscandev.h"

QLsCANDev::QLsCANDev() :
	m_dllUSBtoCANBUS(new QLibrary("USBtoCANBUS.dll")),
	m_thRecv(new QThread),
	m_thRecvIsRunning(true)
{
	m_dllUSBtoCANBUS->moveToThread(m_thRecv);
	moveToThread(m_thRecv);
	m_thRecv->start();

	/* 加载动态库 */
	if(!m_dllUSBtoCANBUS->load())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(m_dllUSBtoCANBUS->errorString());
		return;
	}

	/* 启动子线程接收数据 */
	m_thCANReadDataFuture = QtConcurrent::run(this, &QLsCANDev::slotCANReadData);
}

QLsCANDev::~QLsCANDev()
{
	m_thRecvIsRunning = false;
	m_thCANReadDataFuture.waitForFinished();

	delete m_dllUSBtoCANBUS;
	m_dllUSBtoCANBUS = nullptr;
}

/* 启动设备 */
bool QLsCANDev::GetHidDevice(QString &CLASS_GUID)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(char *);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("GetHidDevice");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char GetHidDevice(char *);'");
		return false;
	}

	/* 执行函数 */
	char tmp[33] = {0};
	if((*fpFun)(tmp))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("启动设备失败");
		return false;
	}

	CLASS_GUID = tmp;
	return true;
}

/* 关闭设备 */
void QLsCANDev::CloseDevice()
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return;
	}

	/* 获取函数接口 */
	typedef void (*FPFUN)();
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("CloseDevice");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'void CloseDevice();'");
		return;
	}

	/* 执行函数 */
	(*fpFun)();
}

/* 设置自测模式 */
bool QLsCANDev::SetModel(unsigned char model/* = 0*/)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetModel");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetModel(unsigned char);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(model))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("设置自检模式失败");
		return false;
	}

	return true;
}

/* 设置验证模式 （厂家保留使用） */
bool QLsCANDev::SetModel2(unsigned char model)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetModel2");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetModel2(unsigned char);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(model))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("设置验证模式失败");
		return false;
	}

	return true;
}

/* 设置CAN接收模式 */
bool QLsCANDev::SetModel3(unsigned char model/* = 1*/)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetModel3");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetModel3(unsigned char);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(model))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("设置CAN接收模式失败");
		return false;
	}

	return true;
}

/* 错误状态复位 */
bool QLsCANDev::ReSetError()
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)();
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("ReSetError");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char ReSetError();'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("错误状态复位失败");
		return false;
	}

	return true;
}

/* CAN复位 */
bool QLsCANDev::ReSetCAN()
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)();
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("ReSetCAN");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char ReSetCAN();'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("CAN复位失败");
		return false;
	}

	return true;
}

/* 设置波特率 */
bool QLsCANDev::SetBaudRate(unsigned char brIndex/* = 0x07 */)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetBaudRate");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetBaudRate(unsigned char);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(brIndex))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("波特率设置错误");
		return false;
	}

	return true;
}

/* 设置地址码 */
bool QLsCANDev::SetSubjectID(unsigned char *SubjectID)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char*);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetSubjectID");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetSubjectID(unsigned char*);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(SubjectID))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("地址码设置错误");
		return false;
	}

	return true;
}

/* 设置屏蔽码 */
bool QLsCANDev::SetMaskCode(unsigned char *Code)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char*);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetMaskCode");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetMaskCode(unsigned char*);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(Code))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("屏蔽码设置错误");
		return false;
	}

	return true;
}

/* 设置过滤码 */
bool QLsCANDev::SetFilterCode(unsigned char *Code)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char*);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SetFilterCode");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SetFilterCode(unsigned char*);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(Code))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("过滤码设置错误");
		return false;
	}

	return true;
}

/* 刷新状态 */
bool QLsCANDev::RefreshStatu(unsigned char *Buffer)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned char*);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("RefreshStatu");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char RefreshStatu(unsigned char*);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(Buffer))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("刷新状态错误");
		return false;
	}

	return true;
}

/* 发送一帧CAN数据 */
bool QLsCANDev::SendCANData(
		unsigned int addr,
		unsigned char ftp1/* = 0*/,
		unsigned char ftp2/* = 0 */,
		unsigned char len/* = -1 */,
		unsigned char *Buffer/* = nullptr */)
{
	if(!Buffer)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("无发送数据");
		return false;
	}

	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return false;
	}

	/* 获取函数接口 */
	typedef char (*FPFUN)(unsigned int, unsigned char, unsigned char,
						  unsigned char, unsigned char *);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("SendCANData");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'char SendCANData(unsigned int, unsigned char, "
					"unsigned char, unsigned char, unsigned char *);'");
		return false;
	}

	/* 执行函数 */
	if((*fpFun)(addr, ftp1, ftp2, len, Buffer))
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("CAN数据发送错误");
		return false;
	}

	return true;
}

/* 接收CAN报文数据 */
int QLsCANDev::RecvData(QLsCANDev::CANMSG *canmsg)
{
	/* 动态库检测 */
	if(!m_dllUSBtoCANBUS->isLoaded())
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg("未加载 USBtoCANBUS.dll");
		return -1;
	}

	/* 获取函数接口 */
	typedef int (*FPFUN)(CANMSG *);
	FPFUN fpFun =(FPFUN)m_dllUSBtoCANBUS->resolve("RecvData");
	if(!fpFun)
	{
		m_errorString = QString("%1:%2").arg(__FUNCTION__).arg(
					"USBtoCANBUS.dll：未找到'int RecvData(CANMSG *);'");
		return -1;
	}

	/* 执行函数 */
	return (*fpFun)(canmsg);
}

QString QLsCANDev::errorString() const
{
	return m_errorString;
}

/* CAN接收数据 的槽函数 */
void QLsCANDev::slotCANReadData()
{
	while(m_thRecvIsRunning)
	{
		/* 获取数据 最大可返回800个 */
		int cnt = RecvData(m_canmsg);
		if(cnt <= 0) continue;

		/* 入缓冲区 */
		m_recvListMutex.lock();
		for(int i = 0; i < cnt; i++)
			m_recvList.append(m_canmsg[i]);
		m_recvListMutex.unlock();

		/* 发送信号 */
		emit sigCANReadyRead();

		/* 延时1ms，防止获取太快占用资源 */
		QThread::msleep(1);
	}
}

/* 接收数据帧个数 */
int QLsCANDev::recvListSize()
{
	QMutexLocker locker(&m_recvListMutex);
	return m_recvList.size();
}

/* 是否有接收数据 */
bool QLsCANDev::hasRecvList()
{
	QMutexLocker locker(&m_recvListMutex);
	return !m_recvList.isEmpty();
}

void QLsCANDev::getRecvCANMSG(QList<QLsCANDev::CANMSG> &recvList,
							  int size/* = 1*/)
{
	QMutexLocker locker(&m_recvListMutex);
	if(size < 0) size = m_recvList.size();
	if(size > m_recvList.size())
	{
		m_errorString = QString("%1:接收的数据不足%2个").arg(__FUNCTION__).arg(size);
		return;
	}
	for(int i = 0; i < size; i++)
	{
		recvList.append(m_recvList.front());
		m_recvList.pop_front();
	}
}
